home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Communication / NewsBase / Source / common.subproj / InfoD.m < prev    next >
Text File  |  1993-01-12  |  8KB  |  309 lines

  1. /*$Copyright:
  2.  * Copyright (C) 1992.5.22. Recruit Co.,Ltd. 
  3.  * Institute for Supercomputing Research
  4.  * All rights reserved.
  5.  * NewsBase  by ISR, Kazuto MIYAI, Gary ARAKAKI, Katsunori SUZUKI, Kok-meng Lue
  6.  *
  7.  * You may freely copy, distribute and reuse the code in this program under 
  8.  * following conditions.
  9.  * - to include this notice in the source code, if it is to be distributed 
  10.  *   with source code.
  11.  * - to add the file named "COPYING" within the code, which shall include 
  12.  *   GNU GENERAL PUBLIC LICENSE(*).
  13.  * - to display an acknowledgement in binary code as follows: "This product
  14.  *   includes software developed by Recruit Co.,Ltd., ISR."
  15.  * - to display a notice which shall state that the users may freely copy,
  16.  *   distribute and reuse the code in this program under GNU GENERAL PUBLIC
  17.  *   LICENSE(*)
  18.  * - to indicate the way to access the copy of GNU GENERAL PUBLIC LICENSE(*)
  19.  *
  20.  *   (*)GNU GENERAL PUBLIC LICENSE is stored in the file named COPYING
  21.  * 
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  23.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  24.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25. $*/
  26. /* InfoD.m */
  27.  
  28. #import "InfoD.h"
  29. #import <appkit/Panel.h>
  30. #import <objc/NXStringTable.h>
  31. #import <objc/objc.h>
  32. #import <objc/hashtable.h>
  33.  
  34. #import <string.h>
  35. #import <libc.h>
  36. #import <ctype.h>
  37. #import <streams/streams.h>
  38. #import "data_types.h"
  39. #import "errdebug.h"
  40.  
  41. #define        DEF_STRT_SIZE        16
  42. #define        DEF_INTT_SIZE        16
  43. #define        STRING_BUF_MAX        256
  44.  
  45. @implementation InfoD
  46.  
  47. static NXAtom fileExtension;
  48.  
  49. + initialize
  50. {
  51.     fileExtension = NXUniqueStringNoCopy("tbl");
  52.     return(self);
  53. }
  54.  
  55. + (NXAtom)rtfControlWord
  56. {
  57.     return(NULL);
  58. }
  59.  
  60. + (NXAtom)fileExtension
  61. {
  62.     return(fileExtension);
  63. }
  64.  
  65. + (NXAtom)pasteboardType
  66. {
  67.     return(NULL);
  68. }
  69.  
  70. - initWithKey:(const char *)theKey strCapacity:(int)kstr_num 
  71.                           intCapacity:(int)kint_num
  72. {
  73.     [super initKeyDesc:"*" valueDesc:"!" capacity:kstr_num + kint_num];
  74.     key = NXCopyStringBufferFromZone(theKey, [self zone]);
  75.     zone = [self zone];
  76.     return(self);
  77. }
  78.  
  79. - initWithKey:(const char *)theKey
  80. {
  81.     [self initWithKey:theKey strCapacity:DEF_STRT_SIZE intCapacity:DEF_INTT_SIZE];
  82.     return self;
  83. }
  84.  
  85. - init
  86. {
  87.     
  88.     [self initWithKey:"" strCapacity:DEF_STRT_SIZE intCapacity:DEF_INTT_SIZE];
  89.     return self;
  90. }
  91.  
  92. - (const char *)key
  93. {
  94.     return(key);
  95. }
  96.  
  97. - addInfo:(char *)kvalue key:(char *)theKey
  98. {
  99.     return([self addInfoString:kvalue key:theKey]);
  100. }
  101.  
  102. - addInfoString:(const char *)theValue key:(const char *)theKey
  103. {
  104.     char *copyOfValue;
  105.     char *copyOfKey;
  106.     
  107.     // save type of value in 4 byte prefix to key
  108.     copyOfKey = NXZoneMalloc(zone, strlen(theKey) + 5);
  109.     *copyOfKey = '*';
  110.     copyOfKey += 4;
  111.     strcpy(copyOfKey, theKey);
  112.     copyOfValue = NXCopyStringBufferFromZone(theValue, zone);
  113.     [super insertKey:(const void *)copyOfKey value:(void *)copyOfValue];
  114.     return(self);
  115. }
  116.  
  117. - addInfoInt:(int)theValue key:(char *)theKey
  118. {
  119.     char *copyOfKey;
  120.  
  121.     // save type of value in 4 byte prefix to key
  122.     copyOfKey = NXZoneMalloc(zone, strlen(theKey) + 5);
  123.     *copyOfKey = 'i';
  124.     copyOfKey += 4;
  125.     strcpy(copyOfKey, theKey);
  126.     [super insertKey:(const void *)copyOfKey value:(void *)theValue];
  127.     return(self);
  128. }
  129.  
  130. - setHeaderInfo:(char *)kheader
  131. {
  132.     NXStream    *stream;
  133.     char    theKey[STRING_BUF_MAX], value[STRING_BUF_MAX];
  134.     
  135.     stream = NXOpenMemory( NULL, 0, NX_READWRITE );
  136.     NXWrite( stream, (const void *)kheader, strlen(kheader) );
  137.     NXSeek( stream, 0, NX_FROMSTART );
  138.     
  139.     while( NXGetc(stream) != (-1) ){
  140.     NXUngetc( stream );
  141.     NXScanf( stream, "%[^: ]", theKey );
  142.         NXGetc( stream );                /* ':' */
  143.         NXGetc( stream );                /* ' ' */
  144.     NXScanf( stream, "%[^\r\n]", value );
  145.         NXGetc( stream );                /* '\r' */
  146.         NXGetc( stream );                /* '\n' */
  147.     [self addInfoString:value key:theKey];
  148.     }
  149.  
  150.     return self;
  151. }
  152.  
  153. - (void *)infoForKey:(const char *)theKey
  154. {
  155.     return([super valueForKey:theKey]);
  156. }
  157.  
  158. - (BOOL)nextState:(NXHashState *)aState key:(const void **)aKey
  159.      value:(void **)aValue
  160. {
  161.     BOOL status;
  162.     static char value[16];
  163.  
  164.     status = [super nextState:aState key:aKey value:aValue];
  165.     if (status == YES) {
  166.         // always return string use prefix to determine type
  167.         if (*(*(const char **)aKey - 4) == 'i') {
  168.              sprintf(value, "%d", *aValue);
  169.              *aValue = value;
  170.         }
  171.     }
  172.     return(status);
  173. }
  174.  
  175. /*
  176.    readFromStream: initializes self from stream.  The stream must be in
  177.    the format specified by RFC822.  readFromStream: returns YES if successful.
  178.    Otherwise readFromStream: returns NO.  Failures occur if the stream is not
  179.    in RFC822 format or there is insufficient space in the buffers.  Lines
  180.    may not be longer than 512 characters.
  181.  
  182.    modified to accept lf in place of cr/lf.
  183. */
  184.  
  185. #define KEY_MAX_SIZE 256
  186. #define VALUE_MAX_SIZE 2048
  187.  
  188. - (BOOL)readFromStream:(NXStream *)stream
  189. {
  190.     char        theKey[KEY_MAX_SIZE];
  191.     char        value[VALUE_MAX_SIZE], *valueEnd;
  192.     char    *ptr;
  193.     int        nextChar;
  194.     int        isNumber;
  195.     BOOL        eos;
  196.  
  197.     while ((eos = NXAtEOS(stream)) == FALSE &&
  198.         (nextChar = NXGetc(stream)) != '\r' && nextChar != '\n') {
  199.         NXUngetc(stream);
  200.         if ((NXScanf(stream, "%255[^:]: %511[^\r\n]", theKey, value)) != 2) {
  201.             return(NO);
  202.         }
  203.         // consume either cr/lf or lf as line terminator
  204.         if ((nextChar = NXGetc(stream)) != '\n') {
  205.             if (nextChar != '\r' || NXGetc(stream) != '\n') {
  206.                 return(NO);
  207.             }
  208.         }
  209.         // read continuation lines if any
  210.         while ((nextChar = NXGetc(stream)) == ' ' || nextChar == '\t') {
  211.             valueEnd = index(value, '\0');
  212.             *valueEnd++ = ' ';
  213.             if (valueEnd + 511 > value + VALUE_MAX_SIZE) {
  214.                 return(NO);
  215.             }
  216.             NXScanf(stream, " %511[^\r\n]", valueEnd);
  217.             // consume either cr/lf or lf as line terminator
  218.             if ((nextChar = NXGetc(stream)) != '\n') {
  219.                 if (nextChar != '\r' || NXGetc(stream) != '\n') {
  220.                     return(NO);
  221.                 }
  222.             }
  223.         }
  224.         NXUngetc(stream);
  225.         DBG(1, fprintf(stderr, "%s %s", theKey, value););
  226.  
  227.         isNumber = 1;
  228.         for (ptr = value; *ptr != '\0'; ++ptr) {
  229.             if ((isNumber = isdigit(*ptr)) == 0) {
  230.                 break;
  231.             }
  232.         }
  233.         if (isNumber != 0) {
  234.             [self addInfoInt:atoi(value) key:theKey];
  235.         } else {
  236.             [self addInfoString:value key:theKey];
  237.         }
  238.     }
  239.     if (eos == FALSE && nextChar == '\r'
  240.         && NXGetc(stream) != '\n') {
  241.         return(NO);
  242.     }
  243.     return(YES);
  244. }
  245.  
  246. - (BOOL)readFromTarStream:(NXStream *)stream
  247. {
  248.     return([self readFromStream:stream]);
  249. }
  250.  
  251. - (BOOL)readFromFile:(const char *)pathName
  252. {
  253.     NXStream *stream;
  254.     BOOL status;
  255.  
  256.     if ((stream = NXMapFile(pathName, NX_READONLY)) != NULL) {
  257.         status = [self readFromStream:stream];
  258.         NXCloseMemory(stream, NX_FREEBUFFER);
  259.         return(status);
  260.     } else {
  261.         return(NO);
  262.     }
  263. }
  264.  
  265.  
  266. - (void)writeToStream:(NXStream *)stream
  267. {
  268.     NXHashState state;
  269.     char *theKey, *value;
  270.  
  271.     state = [self initState];
  272.     while ([super nextState: &state key:(const void**)&theKey
  273.         value:(void **)&value]) {
  274.         if (*(theKey - 4) == '*') {
  275.              NXPrintf(stream, "%s: %s\r\n", theKey, value);
  276.         } else if (*(theKey - 4) == 'i') {
  277.              NXPrintf(stream, "%s: %d\r\n", theKey, value);
  278.         }
  279.     }
  280.     NXPutc(stream, '\r');
  281.     NXPutc(stream, '\n');
  282. }
  283.  
  284. - (void)writeToTarStream:(NXStream *)stream
  285. {
  286.     [self writeToStream:stream];
  287. }
  288.  
  289. - free
  290. {
  291.     NXHashState state;
  292.     char *theKey, *value;
  293.  
  294.     state = [self initState];
  295.     while ([super nextState: &state key:(const void**)&theKey
  296.         value:(void **)&value]) {
  297.         if (*(theKey - 4) == '*') {
  298.             NXZoneFree(zone, theKey - 4);
  299.             NXZoneFree(zone, value);
  300.         } else if (*(theKey - 4) == 'i') {
  301.             NXZoneFree(zone, theKey - 4);
  302.         }
  303.     }
  304.     NXZoneFree(zone, key);
  305.     return([super free]);
  306. }
  307.  
  308. @end
  309.